package com.alperez.recolourbitmap.dsp;

import android.graphics.Bitmap;

public class ColourProcessor {
	private Bitmap mSourceBitmap;
	private int mWidth, mHeight;
	private int mBrightThreshold = 380;
	private int mBackgroundColour = 0xFFFFFFFF;
	private int mBackgroundBrightness = 442;
	
	private int[] mSrcPixels;
	private int mDarkestPixel;
	
	private int mNewAppliedColour;
	private Bitmap mResultBitmap;
	
	/**
	 * 
	 * @param bmp
	 * @param brightnessThresholdPercent
	 * @param bgColour background colour in RRGGBB format, which is used for calculation with Alpha channel
	 */
	public ColourProcessor(Bitmap bmp, int brightnessThresholdPercent, int bgColour) {
		if (bmp == null) {
			throw new IllegalArgumentException("An instance of Bitmap must be provided as a source");
		}
		mSourceBitmap = bmp;
		mWidth = bmp.getWidth();
		mHeight = bmp.getHeight();
		mBrightThreshold = Math.round((float)(442 * brightnessThresholdPercent) / (float)100);
		mBackgroundColour = 0xFF000000 | bgColour;
		mBackgroundBrightness = getBrightness(mBackgroundColour);
		
		
		Bitmap tempBmp = bmp.copy(Bitmap.Config.ARGB_8888, true);
		mSrcPixels = new int[mWidth * mHeight];
		tempBmp.getPixels(mSrcPixels, 0, mWidth, 0, 0, mWidth, mHeight);
		
		int brightness = Integer.MAX_VALUE;
		for (int pixel : mSrcPixels) {
			int newbr = getBrightness(pixel);
			if ((newbr < mBrightThreshold) && (newbr < brightness)) {
				brightness = newbr;
				mDarkestPixel = pixel;
			}
		}
		
		//TODO
	}
	
	public Bitmap getSourceBitmap() {
		return mSourceBitmap;
	}
	
	public Bitmap getResultBitmap() {
		return mResultBitmap;
	}
	
	public int getDarkestPixel() {
		return mDarkestPixel;
	}
	
	public int getRenderedColour(int pixel) {
		int[] colours = ColourProcessor.convertPixelToArgbArray(pixel);
		float alpha = (float)colours[0] / (float)255.0;
		float alpha_1 = (float)1.0-alpha;
		int[] bgColours = ColourProcessor.convertPixelToArgbArray(mBackgroundColour);
		
		int[] rColours = new int[4];
		rColours[0] = 0xFF;
		rColours[1] = Math.round(colours[1]*alpha + alpha_1*bgColours[1]);
		rColours[2] = Math.round(colours[2]*alpha + alpha_1*bgColours[2]);
		rColours[3] = Math.round(colours[3]*alpha + alpha_1*bgColours[3]);
		return ColourProcessor.buildARGBPixelFromComponents(rColours);
	}
	
	public void applyNewColour(int colour) {
		int[] clsNew = ColourProcessor.convertPixelToArgbArray(colour);
		int[] clsOld = ColourProcessor.convertPixelToArgbArray(mDarkestPixel);
		int dR = clsNew[1] - clsOld[1]; 
		int dG = clsNew[2] - clsOld[2]; 
		int dB = clsNew[3] - clsOld[3];
		
		int L = mSrcPixels.length;
		int[] dstPixels = new int[L];
		for (int i=0; i < L; i++) {
			int pixel = mSrcPixels[i];
			int B = getBrightness(pixel);
			if (B < mBrightThreshold) {
				int[] colours = ColourProcessor.convertPixelToArgbArray(pixel);
				colours[1] += dR;
				colours[2] += dG;
				colours[3] += dB;
				if (colours[1] > 255) {
					colours[1] = 255;
				} else if (colours[1] < 0) {
					colours[1] = 0;
				}
				if (colours[2] > 255) {
					colours[2] = 255;
				} else if (colours[2] < 0) {
					colours[2] = 0;
				}
				if (colours[3] > 255) {
					colours[3] = 255;
				} else if (colours[3] < 0) {
					colours[3] = 0;
				}
				dstPixels[i] = ColourProcessor.buildARGBPixelFromComponents(colours);
			} else {
				dstPixels[i] = pixel;
			}
		}
		
		mNewAppliedColour = colour;
		mResultBitmap = Bitmap.createBitmap(dstPixels, mWidth, mHeight, Bitmap.Config.ARGB_8888);
	}
	
	public int getBrightness(int colour) {
		int[] colours = convertPixelToArgbArray(colour);
		if (colours[0] == 0) {
			return mBackgroundBrightness;
		} else if (colours[0] == 255) {
			return Math.round( (float)Math.sqrt(colours[1]*colours[1]+colours[2]*colours[2]+colours[3]*colours[3]) );
		} else {
			double alpha = (double)colours[0] / 255.0;
			return Math.round( (float)(alpha * Math.sqrt(colours[1]*colours[1]+colours[2]*colours[2]+colours[3]*colours[3]) + (1.0-alpha)*mBackgroundBrightness) );
		}
	}
	
	public static int[] convertPixelToArgbArray(int colour) {
		int[] ret = new int[4];
		ret[0] = (colour >> 24) & 0xFF;
		ret[1] = (colour >> 16) & 0xFF;
		ret[2] = (colour >> 8) & 0xFF;
		ret[3] = colour & 0xFF;
		return ret;
	}
	
	public static int buildARGBPixelFromComponents(int[] components) {
		int ret = (components[0] << 24) & 0xFF000000;
		ret += (components[1] << 16) & 0xFF0000;
		ret += (components[2] << 8) & 0xFF00;
		ret += components[3] & 0xFF;
		return ret;
	}
}
